#include <iostream>
#include <iterator>
#include <mutex>
#include <thread>
#include <chrono>
#include <utility>
#include <execution>

class joining_thread
{
private:
    std::thread _t;

public:
    joining_thread() noexcept = default;
    template <typename Callable, typename... Args>
    explicit joining_thread(Callable &&func, Args &&...args) noexcept
        : _t(std::forward<Callable>(func), std::forward<Args>(args)...)
    {
    }
    explicit joining_thread(std::thread t) noexcept : _t(std::move(t)) {}

    joining_thread(joining_thread &&other) noexcept : _t(std::move(other._t)) {}
    joining_thread &operator=(joining_thread &&other) noexcept
    {
        if (this != &other)
        {
            if (_t.joinable())
            {
                _t.join();
            }
        }
        _t = std::move(other._t);
        return *this;
    }
    ~joining_thread() noexcept
    {
        if (joinable())
        {
            join();
        }
    }

    void swap(joining_thread &other) noexcept { _t.swap(other._t); }

    std::thread::id get_id() const noexcept { return _t.get_id(); }

    bool joinable() const noexcept { return _t.joinable(); }

    void join() { _t.join(); }

    void detach() { _t.detach(); }

    std::thread &as_thread() noexcept { return _t; }

    const std::thread &as_thread() const noexcept { return _t; }
};
void do_something()
{
    while (true)
    {
        std::this_thread::sleep_for(std::chrono::seconds(1));
    }
}

void use_jointhread()
{
    // 1 根据线程构造函数构造joiningthread
    joining_thread j1(
        [](int maxindex) {
            for (int i = 0; i < maxindex; i++)
            {
                std::cout << "in thread id " << std::this_thread::get_id()
                          << " cur index is " << i << std::endl;
                std::this_thread::sleep_for(std::chrono::seconds(1));
            }
        },
        10);

    // 2 根据thread构造joiningthread
    joining_thread j2(std::thread(
        [](int maxindex) {
            for (int i = 0; i < maxindex; i++)
            {
                std::cout << "in thread id " << std::this_thread::get_id()
                          << " cur index is " << i << std::endl;
                std::this_thread::sleep_for(std::chrono::seconds(1));
            }
        },
        10));

    // 3 根据thread构造j3
    joining_thread j3(std::thread(
        [](int maxindex) {
            for (int i = 0; i < maxindex; i++)
            {
                std::cout << "in thread id " << std::this_thread::get_id()
                          << " cur index is " << i << std::endl;
                std::this_thread::sleep_for(std::chrono::seconds(1));
            }
        },
        10));

    // 4 把j3赋值给j1，joining_thread内部会等待j1汇合结束后
    // 再将j3赋值给j1
    j1 = std::move(j3);
}
void func1()
{
    std::thread t1(do_something);
    std::thread t2 = std::move(t1);
    t1 = std::thread(do_something);
    std::thread t3;
    t3 = std::move(t2);
    // t3join后,程序就不会崩溃了,说明一个线程原来绑定了资源的话, 是不能
    // 在让另一个线程去绑定这个资源的,必须等原来的线程结束后,资源才会被释放掉
    // t3.join();

    // 不要将一个线程的管理权交给一个已经绑定线程的变量，否则会触发线程的terminate函数引发崩溃。
    t1 = std::move(t3);

    std::this_thread::sleep_for(std::chrono::seconds(2000));
}
template <typename T> class allocatore
{
};
// 全特化必须加template<>
template <> class allocatore<void>
{
};

template <class T> int add(T &a, T &b) { return a + b; }

// 这里的全特化也必须加template<>
template <> int add<std::string>(std::string &a, std::string &b)
{
    return std::stoi(a + b);
}

void func2()
{
    std::thread t1([]() {
        std::cout << "thread id: " << std::this_thread::get_id() << std::endl;
    });
    std::cout << "t1 id :" << t1.get_id() << std::endl;
    t1.join();
}

int main()
{
    // func1();
    // use_jointhread();
    // std::vector<int> vec;
    // for (int i = 0; i < 10; i++)
    //     vec.emplace_back(i);
    // std::cout << std::distance(vec.begin(), vec.end()) << std::endl;
    std::cout << "thread: main: " << std::this_thread::get_id() << std::endl;
    func2();
    return 0;
}